﻿using System;
using System.Linq;
using System.Collections.Generic;
using Bling.DSL;
using Bling.Core;
using Controls = Microsoft.WindowsAPICodePack.DirectX.Controls;
using Microsoft.WindowsAPICodePack.DirectX.Controls;
using Microsoft.WindowsAPICodePack.DirectX.Direct3D10;
using Microsoft.WindowsAPICodePack.DirectX.Direct3D;
using Microsoft.WindowsAPICodePack.DirectX.DXGI;
using Microsoft.WindowsAPICodePack.DirectX.DirectXUtilities;
using DXUtil = Microsoft.WindowsAPICodePack.DirectX.DirectXUtilities;
using Bling.WPF.Custom;
using linq = Microsoft.Linq.Expressions;
using Bling.Linq;
using Bling.Util;
using Bling.Matrices;
using System.Runtime.InteropServices;
using Bling.WPF;
using System.Windows.Controls;
using System.Windows.Interop;

namespace Bling.DX {
  /// <summary>
  /// Hosts DirectX 10 context.
  /// </summary>
  public abstract class HasDX10Canvas : Canvas, ICanStart {
    private class MyDirectHost : DirectHost {}

    private readonly MyDirectHost Host0 = new MyDirectHost();
    public void Start() { if (AlreadyLoaded && ((object)Overlay) != null) Overlay.CurrentValue.Start(); }
    public void Stop() { if (((object)Overlay) != null) Overlay.CurrentValue.Stop(); }
    /// <summary>
    /// The actual element that hosts the DX10 content within this canvas. 
    /// </summary>
    public FrameworkElementBl Host { get { return ((object)Overlay) != null ? Overlay : Host0.Bl(); } }
    /// <summary>
    /// A canvas for WPF content and input overlayed over the DX10 content.
    /// </summary>
    public CanvasBl OverlayContent { get { return Overlay.OverlayContent; } }

    private readonly HasOverlayBl Overlay;
    private bool AlreadyLoaded = false;
    /// <summary>
    /// Device to render DX10 content to.
    /// </summary>
    public readonly RenderDevice Device = new RenderDevice();

    /// <summary>
    /// Initialize a new canvas with an optional overlay for WPF content displayed over DX 10 content.
    /// </summary>
    /// <param name="ActivateOverlay">Use a WPF overlay or not.</param>
    public HasDX10Canvas(bool ActivateOverlay) {
      Host0.Bl().LeftTop = new Double2Bl(0, 0);
      if (ActivateOverlay) {
        Overlay = new HasOverlayBl(this.Bl());
        Host0.Bl().Size = Overlay.Size;
        Host0.Bl().PanelParent = Overlay;
      } else Host.PanelParent = this.Bl();

      RenderDeviceImpl Device0 = null;
      Host0.Loaded += (x, y) => {
        if (AlreadyLoaded) return;
        AlreadyLoaded = true;
        (Device0 == null).Assert();
        var Size = Host.Size.CurrentValue;
        Device0 = new RenderDeviceImpl(Device, Host0.Handle, new Vecs.Vec2<uint>() {
          _0 = (uint)Size[0],
          _1 = (uint)Size[1],
        });
        Device0.InitRender();
        Host0.Render = () => {
          Dispatcher.Invoke(Device0.PreAction, TimeSpan.FromMilliseconds(100));
          Device0.RenderAction();
        };
        Device0.Resize(new Vecs.Vec2<uint>() {
            _0 = (uint)Size[0],
            _1 = (uint)Size[1],
        });

      };
      Host0.SizeChanged += (x, y) => {
        if (Device0 == null) return;
        var Size = Host.Size.CurrentValue;
        Device0.Resize(new Vecs.Vec2<uint>() {
          _0 = (uint)Size[0],
          _1 = (uint)Size[1],
        });
      };

    }
  }
}